#!/bin/sh

# define the base path of project.
CUR_PATH=$(cd "$(dirname "$0")" && pwd)
SPARROW_BASE_PATH=$CUR_PATH

# cd base dir of project.
# the process is in the same shell as the starting shell.
cd $SPARROW_BASE_PATH

# extract command
COMMAND=$1
if [ "${COMMAND}" = "upload" ]; then
    VAR_IS_UPLOAD_COMMAND=true
    shift # pass all params and remove the first argument: mupload
elif [ "${COMMAND}" = "mupload" ]; then
    VAR_IS_MUPLOAD_COMMAND=true
    shift # pass all params and remove the first argument: mupload
elif [ "${COMMAND}" = "new" ]; then
    VAR_IS_NEW_COMMAND=true
    shift # pass all params and remove the first argument: mupload
elif [ "${COMMAND}" = "env" ]; then
    VAR_IS_ENV_COMMAND=true
    shift # pass all params and remove the first argument: mupload
    VAR_RUNTIME_NO_PRINT_MESSAGE="ON" # no print message
elif [ "${COMMAND}" = "clear" ]; then
    VAR_IS_CLEAR_COMMAND=true
elif [ "${COMMAND}" = "tip" ] || [ "${COMMAND}" = "tips" ]; then
    VAR_IS_TIP_COMMAND=true
elif [ "${COMMAND}" = "help" ] || [ "${COMMAND}" = "--help" ] || [ "${COMMAND}" = "h" ] || [ "${COMMAND}" = "-h" ]; then
    VAR_IS_HELP_COMMAND=true
    VAR_RUNTIME_NO_PRINT_MESSAGE="ON" # no print message
else
    echo "not support command: ${COMMAND} (Unknown command: ${COMMAND})"
    exit 1
fi

# include sdk of sparrow.
. .work/include/sdk.sh

# new something.
new() {
    while getopts "t:s:p:v:" opt; do
    case $opt in
        t)
        type="$OPTARG"
        ;;
        s)
        service="$OPTARG"
        service_upper=$(echo "$service" | awk '{print toupper($0)}')
        ;;
        p)
        service_port="$OPTARG"
        ;;
        v)
        service_version="$OPTARG"
        image_basic_version=$service_version
        image_app_version=latest
        ;;
        \?)
        echo "invalid option: -$OPTARG" >&2
        exit 1
        ;;
    esac
    done

    print_info "must options: type=$type, service=$service"
    if [ "$type" == "" ] || [ "$service" == "" ]; then
        print_error "miss option: type/service"
        exit 1
    fi
    if [ "$type" != "service" ]; then
        print_error "type error: ${type}"
        exit 1
    fi

    # create service
    if [ -d "./$service" ]; then
        print_error "service exists!"
        exit 1
    elif ! mkdir -p ./$service; then
        print_error "mkdir ./$service failed"
        exit 1
    elif ! cp -r "${CONST_SERVICE_EXAMPLE_DIR}/" ./$service/; then
        print_error "cp failed"
        exit 1
    fi
    find "${CONST_SERVICE_EXAMPLE_DIR}" -type f -print0 | while IFS= read -r -d '' file; do
        relative_path="${file#$CONST_SERVICE_EXAMPLE_DIR}"
        if [ "$relative_path" == "/.DS_Store" ]; then
            continue
        fi

        print_info "rewrite file: ./${service}/${relative_path}"
        sed -e "s/{{SERVICE}}/$service/g" \
        -e "s/{{SERVICE_UPPER}}/$service_upper/g" \
        -e "s/{{SERVICE_PORT}}/$service_port/g" \
        -e "s/{{IMAGE_BASIC_VERSION}}/$image_basic_version/g" \
        -e "s/{{IMAGE_APP_VERSION}}/$image_app_version/g" \
        "${CONST_SERVICE_EXAMPLE_DIR}/${relative_path}" > "./${service}/${relative_path}"
    done

    print_warn "In order to avoid confusion in port number allocation, it is recommended to use './sparrowtool env -l _port ' this command to view the current range of port number."
}

# show some tips.
tip() {
    # -u root: fix error(https://stackoverflow.com/questions/37836124/i-have-no-name-as-user-logging-into-jenkins-in-a-docker-container-that-uses-t)
    echo "docker exec -w '/' -u root -it sparrow_container_${CONTAINER_NAMESPACE}_go bash"
    echo "docker exec -w '/' -u root -it sparrow_container_${CONTAINER_NAMESPACE}_nginx bash"
    echo "docker exec -w '/' -u root -it sparrow_container_${CONTAINER_NAMESPACE}_mysql bash"
    echo "docker exec -w '/' -u root -it sparrow_container_${CONTAINER_NAMESPACE}_redis bash"

    echo "docker exec -w '/' -u root -it sparrow_container_${CONTAINER_NAMESPACE}_mysql bash -c 'mysql -u ${MYSQL_ROOT_USER} -h 127.0.0.1 -p${MYSQL_ROOT_PASSWORD} -P${MYSQL_CONTAINER_PORT} --default-character-set=utf8'"
    echo "docker exec -w '/' -u root -it sparrow_container_${CONTAINER_NAMESPACE}_redis bash -c 'redis-cli -h 127.0.0.1 -p ${REDIS_CONTAINER_PORT} -a ${REDIS_PASSWORD}'"
}

# help document.
help() {
    printf "welcome to sparrowtool\n"
    printf "\n"
    printf "1、about create.\n"
    printf "(1) create service: ./sparrowtool new -t service -s {service_name} -p port -v {version}\n"
    printf "    ① params: -t(type:service) / -s(service) / -p(port) / -v(version)\n"
    printf "    ② example 1: ./sparrowtool new -s prometheus -p 9876 -v 0.0.98\n"
    printf "\n"
    printf "2、about container.\n"
    printf "(1) enter container: ./sparrowtool enter {service?}\n"
    printf "    ① param: if you pass nothing, if will enter all containers.\n"
    printf "    ② example 1: ./sparrowtool enter\n"
    printf "    ② example 2: ./sparrowtool enter go\n"
    printf "\n"
    printf "3、about image.\n"
    printf "(1) upload image: ./sparrowtool upload -t(type:app|basic) -s(service) -v(version) -r(replace)\n"
    printf "    ① param: {app}means the application image, {basic}means the basic image, {service}means the name of service.\n"
    printf "    ② example 1: ./sparrowtool upload -t basic -s etcd -v 3.5.0\n"
    printf "(2) mupload image: ./sparrowtool mupload {service1} {service2} ...\n"
    printf "    ① param: mupload means multi/batch upload\n"
    printf "    ② example 1: ./sparrowtool mupload etcd kafka mysql\n"
    printf "\n"
    printf "4、about env.\n"
    printf "(1) list all matched environment variables in /env file : ./sparrowtool env -l {match_pattern}\n"
    printf "    ① param: -l(match_pattern)\n"
    printf "    ① example 1: ./sparrowtool env -l port\n"
    printf "\n"
    printf "5、about clear.\n"
    printf "(1) clear one service or some services : ./sparrowtool clear {service1} {service2} ...\n"
    printf "    ① example 1: ./sparrowtool clear redis nginx mongodb jupyter\n"
    printf "\n"
    printf "5、about tip.\n"
    printf "(1) show all tips : ./sparrowtool tip\n"
    printf "\n"
    printf "========================================================\n"
}

# search the matched variables in /env file
search_env() {
    while getopts "l:" opt; do
    case $opt in
        l)
        arg=$(echo "$OPTARG" | awk '{print toupper($0)}')
        pattern=".*$arg.*"
        ;;
        \?)
        echo "invalid option: -$OPTARG" >&2
        exit 1
        ;;
    esac
    done

    # search these directory
    subdirectories=("etcd" "etcdkeeper" "go" "jupyter" "kafka" "kafkaui" "mysql" "nginx" "phpfpm" "postgres" "python" "redis" "zookeeper" "langchain" "nodejs" "mongodb" "ssdb" "prometheus" "grafana" "elasticsearch" "kibana" "prompthub" "nacos") # when you create a new service, then append it to the subdirectories variable
    for dir in "${subdirectories[@]}"; do
        # show the service information
        if [ "$start_port" == "" ]; then
            start_port=1900
        fi
        start_port=$((start_port + 100))
        end_port=$((start_port + 100))
        printf "${dir} service (the port range of host: [$start_port, $end_port))\n===========================================================\n"

        # search pattern in the env file.
        env_file="$dir/${CONST_SPARROW_CONFIG_ENV_FILE}"
        if [ ! -f "$env_file" ]; then
            continue
        fi
        while IFS= read -r line; do
            # ignore comments.
            if [[ "$line" =~ ^\# ]]; then
                continue
            fi

            if echo "$line" | grep -q "$pattern"; then
                key=$(echo "$line" | cut -d '=' -f1)
                value=$(echo "$line" | cut -d '=' -f2-)
                printf "${key}=${value}\n"
            fi
        done < "$env_file"
        printf "\n"
    done
}

# multi upload.
multi_upload() {
    service_list=("$@")
    print_info "service_list: ${service_list[@]}, count: ${#service_list[@]}"
    for service in "${service_list[@]}"; do
        service_upper=$(echo "$service" | awk '{print toupper($0)}')
        print_info "current service: ${service}"

        # image_basic_version
        version_name="IMAGE_BASIC_${service_upper}_VERSION"
        image_basic_version=$(eval echo "$"$version_name)
        # image_app_version
        version_name="IMAGE_APP_${service_upper}_VERSION"
        image_app_version=$(eval echo "$"$version_name)

        # Notice: maybe the basic/app image is not in local

        cmd="upload -t basic -s $service -v $image_basic_version"
        print_info "single upload command 1: $cmd"
        if ! ($cmd) ; then
            print_error "single upload error 1, maybe the basic image is not in local"
            exit 1
        fi

        cmd="upload -t basic -s $service -v $image_basic_version -r true"
        print_info "single upload command 2: $cmd"
        if ! ($cmd) ; then
            print_error "single upload error 2"
            exit 1
        fi

        cmd="upload -t app -s $service -v $image_app_version"
        print_info "single upload command 3: $cmd"
        if ! ($cmd) ; then
            print_error "single upload error 3, maybe the app image is not in local"
            exit 1
        fi

        cmd="upload -t app -s $service -v $image_app_version -r true"
        print_info "single upload command 4: $cmd"
        if ! ($cmd) ; then
            print_error "single upload error 4"
            exit 1
        fi
    done
}

# clear service.
clear() {
    service_list=("$@")
    print_info "clear service_list: ${service_list[@]}, count: ${#service_list[@]}"
    for service in "${service_list[@]}"; do
        # clear the resources of the service
        clear_service_resources $service
    done
}

# before run sparrowtool command.
before_sparrowtool_command() {
    print_stage "do before_sparrowtool_command..."
}

# after run sparrowtool command.
after_sparrowtool_command() {
    print_stage "do after_sparrowtool_command..."
}

##################### start script exec flow #####################

# before run sparrowtool command.
before_sparrowtool_command

# when run sparrowtool command.
if [ "${VAR_IS_UPLOAD_COMMAND}" = true ]; then
    upload "$@"
elif [ "${VAR_IS_MUPLOAD_COMMAND}" = true ]; then
    multi_upload "$@"
elif [ "${VAR_IS_NEW_COMMAND}" = true ]; then
    new "$@"
elif [ "${VAR_IS_ENV_COMMAND}" = true ]; then
    search_env "$@"
elif [ "${VAR_IS_CLEAR_COMMAND}" = true ]; then
    clear "$@"
elif [ "${VAR_IS_TIP_COMMAND}" = true ]; then
    tip
elif [ "${VAR_IS_HELP_COMMAND}" = true ]; then
    help
fi

# after run sparrowtool command.
after_sparrowtool_command

##################### end script exec flow #######################
